﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;

namespace PivotBeer
{
    enum PivotType
    {
        String,
        LongString,
        Number,
        DateTime,
        Link
    }

    [AttributeUsage(AttributeTargets.Field)]
    class PivotField : Attribute
    {
        public PivotField( PivotType pt)
        {
            format = "";
            type = pt;
        }

        public string format;
        public PivotType type;
    }

    

    class PivotCreator<T>
    {
        StreamWriter sw;
        Dictionary<string, PivotType> types;
        Dictionary<string, FieldInfo> fields;

        public PivotCreator(string filename, string name, string imagebase)
        {
            sw = new StreamWriter( new FileStream(filename, FileMode.Create, FileAccess.Write), Encoding.UTF8);
            types = new Dictionary<string,PivotType>();
            fields = new Dictionary<string, FieldInfo>();
            Type t = typeof(T);

            WriteOut("<?xml  version=\"1.0\"?><Collection Name=\"" + name + "\" SchemaVersion=\"1.0\" xmlns=\"http://schemas.microsoft.com/collection/metadata/2009\" xmlns:p=\"http://schemas.microsoft.com/livelabs/pivot/collection/2009\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><FacetCategories>");

            foreach (FieldInfo f in t.GetFields(BindingFlags.Instance | BindingFlags.Public))
            {
                PivotField[] fieldInfoArr = (PivotField[])f.GetCustomAttributes(typeof(PivotField), true);
                if (fieldInfoArr.Count() == 1)
                {
                    PivotField pf = fieldInfoArr[0];
                    
                    types.Add(f.Name, pf.type);
                    fields.Add(f.Name, f);

                    if (pf.format != "")
                    {
                        WriteOut("<FacetCategory Name=\"" + f.Name + "\" Format=\"" + pf.format + "\" Type=\"" + pf.type.ToString() + "\"/>");
                    }
                    else
                    {
                        WriteOut("<FacetCategory Name=\"" + f.Name + "\" Type=\"" + pf.type.ToString() + "\"/>");
                    }
                }
            }
       


            WriteOut("</FacetCategories><Items ImgBase=\"" + imagebase + "\">");
        }

        string[] ConvertObjectToPivotValue(T item, FieldInfo f, PivotType pt)
        {
            //1938-06-26T00:00:00
            object o = f.GetValue(item);
            if (o.GetType().IsArray)
            {
                object[] arr = (object[])o;
                
                List<string> temp = new List<string>();
                foreach (object i in arr)
                {
                    temp.Add(ConvertSingleValue(i, pt));
                }
                return temp.ToArray();
            }
            else
            {
                return new string[] { ConvertSingleValue(o,pt) };
            }
            
        }

        string ConvertSingleValue(object o, PivotType pt)
        {
            return o.ToString();
        }

        public void AddItem(T item, uint img, int id, string link, string name, string desc)
        {
            WriteOut("<Item Img=\"#" + img + "\" Id=\"" + id + "\" Href=\"" + link + "\" Name=\"" + name + "\">");
            WriteOut("<Description>" + desc + "</Description><Facets>");
            foreach(FieldInfo f in fields.Values){
                PivotType pt = types[f.Name];
                string[] values = ConvertObjectToPivotValue(item, f, pt);

                if ((values != null) && !values.Contains(null))
                {
                    WriteOut("<Facet Name=\"" + f.Name + "\">");
                    foreach (string v in values)
                    {
                        WriteOut("<" + pt.ToString() + " Value=\""+ v +"\"/>");
                    }
                    WriteOut("</Facet>");
                }
            }

            WriteOut("</Facets></Item>");
        }

        public void Close()
        {
            WriteOut("</Items></Collection>");
            sw.Close();
        }

        private void WriteOut(string data)
        {
            Console.WriteLine(data);
            sw.WriteLine(data);
        }
    }
}
